/*
 * Author: 李波(Edwin Lee)
 * Date: 2024-08-20 15:00:39
 * FilePath: /mprpc/src/logger.cc
 * LastEditTime: 2024-09-03 09:05:58
 * version: 1.0
 * Description: 
 */
#include "public.h"
#include "logger.h"
#include <thread>
#include <iostream>

Logger::~Logger()
{
	if (nullptr != logfile_)
	{
		fclose(logfile_);
	}
}

Logger& Logger::getInstance()
{
    static Logger log;
    return log;
}

Logger::Logger(std::string dir)
	: dir_(dir)
    , logfile_(nullptr)
	, cache_(true)
	, backup_(true)
	, debug_(false)
	, maxLogFileSize_(10)
	, time_()
{
    // 获取当前日期，然后取体制信息，写入相应的日志文件当中 a+
    filename_ = dir_ + time_.getDate("yyyymmddhh24miss") + ".log";
    if(nullptr == (logfile_ = FOPEN(filename_.c_str(),"a+")))
    {
        std::cout << "Logger::Logger(): FOPEN(" << filename_ << " failed!" << std::endl;
        return;
    }
    // 启动专门写日志的线程
	std::thread writeLogTask([&]()
	{
		for(;;)
		{
			if(nullptr == logfile_)
			{
				std::string filename_ = dir_ + time_.getDate("yyyymmddhh24miss") + ".log";
				if (nullptr == (logfile_ = FOPEN(filename_.c_str(), "a+")))
				{
					std::cout << "Logger::Logger(): FOPEN(" << filename_ << " failed!" << std::endl;
					exit(EXIT_FAILURE);
				}
			}
			if (backup_)
			{
				if (!backupLogFile())
				{
					std::cout << "Logger::info backupLogFile failed!" << std::endl;
					return false;
				}
			}
			std::string msg = this->lckQue_.pop();
			fputs(msg.c_str(), logfile_);
			if (!cache_)
				fflush(logfile_);
		} 
	});

	writeLogTask.detach();
}

void Logger::setMaxLogFileSize(size_t size) noexcept
{
	if (size >= 10)
	{
		maxLogFileSize_ = size;
	}
	else
	{
		maxLogFileSize_ = 10;
	}
}

bool Logger::info(const char* fmt, ...)
{
	char msgHeader[24]{0};
	sprintf(msgHeader, "%s %s ", time_.getDate("yyyymmddhh24miss").c_str(), "[info]");
	char msgContent[MAX_LOGGER_MSG]{0};
	va_list ap;
	va_start(ap, fmt);
	vsprintf(msgContent, fmt, ap);
	va_end(ap);
	std::string msg(msgHeader);
	msg = msg + msgContent + "\n";
	lckQue_.push(msg);
	return true;
}

bool Logger::error(const char* fmt, ...)
{
	char msgHeader[24]{0};
	sprintf(msgHeader, "%s %s ", time_.getDate("yyyymmddhh24miss").c_str(), "[error]");
	char msgContent[MAX_LOGGER_MSG]{0};
	va_list ap;
	va_start(ap, fmt);
	vsprintf(msgContent, fmt, ap);
	va_end(ap);
	std::string msg(msgHeader);
	msg = msg + msgContent + "\n";
	lckQue_.push(msg);
	return true;
}

bool Logger::fatal(const char* fmt, ...)
{
	char msgHeader[24]{0};
	sprintf(msgHeader, "%s %s ", time_.getDate("yyyymmddhh24miss").c_str(), "[fatal]");
	char msgContent[MAX_LOGGER_MSG]{0};
	va_list ap;
	va_start(ap, fmt);
	vsprintf(msgContent, fmt, ap);
	va_end(ap);
	std::string msg(msgHeader);
	msg = msg + msgContent + "\n";
	lckQue_.push(msg);
	return true;
}

bool Logger::debug(const char* fmt, ...)
{
	if (this->debug_)
	{
		char msgHeader[24]{0};
		sprintf(msgHeader, "%s %s ", time_.getDate("yyyymmddhh24miss").c_str(), "[debug]");
		char msgContent[MAX_LOGGER_MSG]{0};
		va_list ap;
		va_start(ap, fmt);
		vsprintf(msgContent, fmt, ap);
		va_end(ap);
		std::string msg(msgHeader);
		msg = msg + msgContent + "\n";
		lckQue_.push(msg);
		return true;
	}
	return true;
}

bool Logger::log(const char* fmt, ...)
{
	char msgContent[MAX_LOGGER_MSG]{0};
	va_list ap;
	va_start(ap, fmt);
	vsprintf(msgContent, fmt, ap);
	va_end(ap);
	std::string msg(msgContent);
	lckQue_.push(msg);
	return true;
}

bool Logger::backupLogFile()
{
	if (maxLogFileSize_ * 1024 * 1024 <= static_cast<size_t>(ftell(logfile_)))
	{
		std::string bakFilename(filename_,0,filename_.size()-4);
		bakFilename = bakFilename + "-" + time_.getDate("yyyymmddhh24miss") + ".log";
		fclose(logfile_);
		logfile_ = nullptr;
		if (!RENAME(filename_.c_str(), bakFilename.c_str()))
			return false;
		filename_ = dir_ + time_.getDate("yyyymmddhh24miss") + ".log";
		if (nullptr == (logfile_ = FOPEN(filename_.c_str(), "a+")))
			return false;
	}
	return true;
}